﻿using System;
using System.Linq;

using zijian666.Converts.Abstractions;
using zijian666.Converts.Convertor.Base;
using zijian666.Converts.Extensions;

namespace zijian666.Converts.Core;

/// <summary>
/// 转换程序编译器
/// </summary>
public class ConvertorBuilder
{
    /// <summary>
    /// 转换器工厂
    /// </summary>
    private readonly IConvertorFactory[] _factories;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="factories">转换器工厂集合</param>
    /// <exception cref="ArgumentNullException"></exception>
    public ConvertorBuilder(IConvertorFactory[] factories!!)
    {
        if (factories.Length == 0)
        {
            throw new ArgumentException("集合为空", nameof(factories));
        }
        _factories = factories;
    }

    /// <summary>
    /// 编译转换器
    /// </summary>
    public IConvertor<T> Build<T>()
    {
        var outputType = typeof(T);
        if (outputType.IsGenericTypeDefinition)
        {
            return new TraceConvertor<T>(new CantBuildConvertor<T>(outputType.GetFriendlyName(), nameof(ResourceStrings.CLASS_IS_GENERIC_TYPE_DEFINITION)));
        }
        if (outputType.IsAbstract && outputType.IsSealed)
        {
            return new TraceConvertor<T>(new CantBuildConvertor<T>(nameof(ResourceStrings.CLASS_IS_STATIC)));
        }
        if (outputType == typeof(object[]))
        {
            Console.WriteLine();
        }
        var convs = _factories
            .Select(x => x.Create<T>())
            .Where(x => x.MacthedType != MacthedType.NotMatched)
            .OrderBy(x => x.MacthedType)                    // 根据匹配类型排序
            .ThenByDescending(x => x.Convertor.Priority)    // 然后根据转换器优先级倒序
            .Select(x => new TraceConvertor<T>(x.Convertor))// 创建带日志的转换器
            .ToList();

        return convs.Count switch
        {
            0 => new TraceConvertor<T>(new CantBuildConvertor<T>(nameof(ResourceStrings.CONVERTOR_NOT_FOUND))),
            1 => convs.FirstOrDefault(),
            _ => new TraceConvertor<T>(new AggregateConvertor<T>(convs)),
        };
    }
}
